<?php

namespace App\Libraries\Ext;

use \CodeIgniter\Exceptions\PageNotFoundException;

class MyRouter extends \CodeIgniter\Router\Router
{

    /**
     * Attempts to match a URI path against Controllers and directories
     * found in APPPATH/Controllers, to find a matching route.
     *
     * @param string $uri
     */
    public function autoRoute(string $uri)
    {
        $segments = explode('/', $uri);

        $segments = $this->validateRequest($segments);
        $file = null;

        // If we don't have any segments left - try the default controller;
        // WARNING: Directories get shifted out of the segments array.

        
        if (empty($segments)) {
            $this->setDefaultController();
        } // If not empty, then the first segment should be the controller
        else {
            
            if (stristr($segments[0], '.php')) {
                array_shift($segments);
            }

            if (!empty($segments) && !$this->directory) {

                if (is_file(APPPATH . 'Controllers/' . ucfirst($segments[0]) . '.php')) {
                    $this->controllerName = $this->controller = ucfirst(array_shift($segments));
                    if (!empty($segments)) {
                        $this->methodName = $this->method = array_shift($segments);
                    }
                    
                } elseif (is_dir(APPPATH . 'Controllers/' . ucfirst($segments[0]))) {
                    $this->directory = ucfirst(array_shift($segments)) . '/';
                    if (!empty($segments)) {
                        $this->controllerName = $this->controller = ucfirst(array_shift($segments));
                    }
                    if (!empty($segments)) {
                        $this->methodName = $this->method = array_shift($segments);
                    }

                } elseif (is_dir(APPSPATH . ucfirst($segments[0]) . '/')) {

                    define('MODDIR', ucfirst($segments[0]));

                    $this->collection->setAppsDefaultNamespace('Apps\\' . ucfirst($segments[0]) . '\Controllers');

                    $appcontrollers = ucfirst(array_shift($segments)) . '/Controllers';

                    //模块判断
                    if (!empty($segments)) {
                        if (is_file(APPSPATH . $appcontrollers . '/' . ucfirst($segments[0]) . '.php')) {
                            $this->directory = null;
                            $this->controllerName = $this->controller = ucfirst(array_shift($segments));
                            if (!empty($segments)) {
                                $this->methodName = $this->method = array_shift($segments);
                            }
                            $file = APPSPATH . $appcontrollers . '/' . $this->controllerName . '.php';
                        } elseif (is_dir(APPSPATH . $appcontrollers . '/' . ucfirst($segments[0]))) {
                            $this->directory = ucfirst(array_shift($segments)) . '/';
                            if (!empty($segments)) {
                                $this->controllerName = $this->controller = ucfirst(array_shift($segments));
                            }
                            if (!empty($segments)) {
                                $this->methodName = $this->method = array_shift($segments);
                            }
                            // $file = APPSPATH . $appcontrollers . '/' . $this->directory . 'Home.php';
                        }
                    }else{
                        $this->controllerName = $this->controller = 'Home';
                        $this->methodName = $this->method = 'index';
                    }
                    $file = APPSPATH . $appcontrollers . '/' . $this->directory . 'Home.php';
                    
                } else {
                    throw new PageNotFoundException();
                }
            } elseif ($this->directory) {
                if (!empty($segments)) {
                    $this->controllerName = $this->controller = ucfirst(array_shift($segments));
                }
                if (!empty($segments)) {
                    $this->methodName = $this->method = array_shift($segments);
                }
            }
        }
        if (!defined('MODDIR')) {
            define('MODDIR', ''); //主项目
        }

        // $this->controller = ucfirst(array_shift($segments));
        // Use the method name if it exists.
        // If it doesn't, no biggie - the default method name
        // has already been set.
        // if (!empty($segments)) {
        //     $this->method = array_shift($segments);
        // }

        if (!empty($segments)) {
            $this->params = $segments;
        }

        if ($this->collection->getHTTPVerb() !== 'cli') {
            $controller = '\\' . $this->collection->getDefaultNamespace();
            $controller .= $this->directory ? str_replace('/', '\\', $this->directory) : '';
            $controller .= $this->controllerName();
            $controller = strtolower($controller);
            $methodName = strtolower($this->methodName());
            foreach ($this->collection->getRoutes('cli') as $route) {
                if (is_string($route)) {
                    $route = strtolower($route);
                    if (strpos($route, $controller . '::' . $methodName) === 0) {
                        throw new PageNotFoundException();
                    }

                    if ($route === $controller) {
                        throw new PageNotFoundException();
                    }
                }
            }
        }

        // Load the file so that it's available for CodeIgniter.
        if (!$file) {
            $file = APPPATH . 'Controllers/' . $this->directory . $this->controllerName() . '.php';
        } elseif (is_file($file)) {
            include_once $file;
        }

        // Ensure the controller stores the fully-qualified class name
        // We have to check for a length over 1, since by default it will be '\'
        if (strpos($this->controller, '\\') === false && strlen($this->collection->getDefaultNamespace()) > 1) {
            $this->controller = '\\' . ltrim(str_replace('/', '\\', $this->collection->getDefaultNamespace() . $this->directory . $this->controllerName()), '\\');
        }

    }

    /**
     * Attempts to validate the URI request and determine the controller path.
     *
     * @param array $segments URI segments
     *
     * @return array URI segments
     */
    protected function validateRequest(array $segments): array
    {
        $segments = array_filter($segments, function ($segment) {
            return !empty($segment) || ($segment !== '0' || $segment !== 0);
        });
        $segments = array_values($segments);

        $c = count($segments);
        $directory_override = isset($this->directory);

        // Loop through our segments and return as soon as a controller
        // is found or when such a directory doesn't exist
        while ($c-- > 0) {
            $test = $this->directory . ucfirst($this->translateURIDashes === true ? str_replace('-', '_', $segments[0]) : $segments[0]);
            if (!is_file(APPPATH . 'Controllers/' . $test . '.php') && $directory_override === false && is_dir(APPPATH . 'Controllers/' . $this->directory . ucfirst($segments[0]))) {
                $this->setDirectory(array_shift($segments), true);
                continue;
            }
            return $segments;
        }

        // This means that all segments were actually directories
        return $segments;
    }

    protected function setDefaultController()
    {

        if (empty($this->controller)) {
            throw RouterException::forMissingDefaultRoute();
        }

        // Is the method being specified?
        if (sscanf($this->controller, '%[^/]/%s', $class, $this->method) !== 2) {
            $this->method = 'index';
        }

        if (!is_file(APPPATH . 'Controllers/' . $this->directory . ucfirst($class) . '.php')) {
            return;
        }

        $this->controller = ucfirst($class);

        log_message('info', 'Used the default controller.');
    }

}
